package cn.tonyandmoney.voicenotes.alarm.model

import cn.tonyandmoney.baidu.tts.event.SynthesizeListener
import cn.tonyandmoney.voicenotes.wav.utils.AudioEncodeUtil
import io.reactivex.ObservableEmitter
import java.io.File
import java.io.FileOutputStream
import java.io.IOException

class FileWriterEmitter(private val emitter: ObservableEmitter<String>,
                        private val outPath: String,
                        private val progressListener: (Int) -> Unit) : SynthesizeListener {


    private val file: File
    private val outputStream: FileOutputStream

    init {
        file = checkOutFile()
        outputStream = FileOutputStream(file)
    }

    override fun onSynthesizeDataArrived(id: String, data: ByteArray, progress: Int) {
        if (!emitter.isDisposed) {
            try {
                progressListener.invoke(progress)
                writeTo(data)
            } catch (e: Exception) {
                emitter.onError(e)
            }
        } else {
            convertToWav()
        }
    }

    override fun onSynthesizeFinish(id: String) {
        val finalPath = convertToWav()
        if (!emitter.isDisposed) {
            emitter.onNext(finalPath)
            emitter.onComplete()
        }
    }

    override fun onSynthesizeStart(id: String) {
        progressListener.invoke(0)
    }

    @Throws(IOException::class)
    private fun convertToWav(): String {
        outputStream.flush()
        outputStream.close()
        val finalPath = outPath.replace(".pcm", ".wav")
        val fFile = File(finalPath)
        if (!fFile.exists()) fFile.createNewFile()
        AudioEncodeUtil.convertPcm2Wav(outPath, finalPath, 16000, 1, 16)
        file.delete()
        return finalPath
    }

    private fun checkOutFile(): File {
        val outFile = File(outPath)
        if (!outFile.parentFile.exists()) outFile.parentFile.mkdirs()
        outFile.createNewFile()
        return outFile
    }

    @Throws(IOException::class)
    private fun writeTo(bytes: ByteArray) {
        outputStream.write(bytes)
    }

}